#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import json
import argparse

from enum import Enum

current_file_path = os.path.abspath(__file__)
current_directory = os.path.dirname(current_file_path)

clerk_sp_info_dic = {}
clerk_skills_dic = {}


class ClerkAbilityType(Enum):
    eloq = 1
    cashier = 2
    restock = 3
    speed = 4
    build = 6
    carry = 5
    luck = 7


class ClerkDutyType(Enum):
    收银 = 1
    补货 = 2
    建造 = 3
    搬运 = 4
    剁手节_收银 = 101
    剁手节_补货 = 102
    剁手节_安保 = 103
    剁手节_搞事 = 104


class ClerkSPInfoVO:
    def __init__(self, arg):
        self.id = int(str(arg['id']))
        self.name = str(arg['name'])
        self.desc = str(arg['desc'])
        self.asset = str(arg['asset'])
        self.defaultLv = int(str(arg['defaultLv']))
        self.defaultEdu = int(str(arg['defaultEdu']))
        self.defaultMajor = int(str(arg['defaultMajor']))
        self.mgrSkill = int(str(arg['mgrSkill']))
        self.isRandom = int(str(arg['isRandom']))
        self.unlockDesc = str(arg['unlockDesc'])
        self.defaultSkills = []
        text = str(arg['defaultSkills'])
        if text != '-1':
            for text2 in text.split(','):
                self.defaultSkills.append(int(text2))
        self.defaultPotential = {}
        array = str(arg['defaultPotential']).split('|')
        for array2 in array:
            array3 = array2.split(',')
            self.defaultPotential[ClerkAbilityType(int(array3[0])).name] = int(array3[1])
        self.defaultPotential[ClerkAbilityType.luck.name] = 0
        self.defaultAbility = {}
        array = str(arg['defaultAbility']).split('|')
        for array2 in array:
            array3 = array2.split(',')
            self.defaultAbility[ClerkAbilityType(int(array3[0])).name] = int(array3[1])
        self.defaultAbility[ClerkAbilityType.luck.name] = 0

    def __str__(self):
        return str(self.__dict__)


class ClerkSkillsVO:
    def __init__(self, arg):
        self.id = int(str(arg['id']))
        self.name = str(arg['name'])
        self.desc = str(arg['desc'])
        self.prefer = int(str(arg['prefer']))
        self.isRefresh = True if str(arg['isRefresh']) == '1' else False
        self.isRandom = True if str(arg['isRandom']) == '1' else False
        self.mutex = [int(text) for text in str(arg['mutex']).split(',')]

    def __str__(self):
        return str(self.__dict__)


class ClerkData:
    MaxPotential = 150

    def __init__(self, arg=None):
        if arg is None:
            arg = {}
        self.id = int(arg.get('id', -1))
        self.spID = int(arg.get('spID', -1))
        self.name = arg.get('name', '')
        self.headAssets = arg.get('headAssets', '')
        self.bodyAssets = arg.get('bodyAssets', '')
        self.entryDay = int(arg.get('entryDay', 0))
        self.lv = int(arg.get('lv', 1))
        self.baseLV = int(arg.get('baseLV', 1))
        self.exp = int(arg.get('exp', 0))
        self.eduType = int(arg.get('eduType', 0))
        self.majorType = int(arg.get('majorType', 0))
        self.defaultSalary = int(arg.get('defaultSalary', 0))
        self.salary = int(arg.get('salary', 0))
        self.hp = int(arg.get('hp', 0))
        self.job = int(arg.get('job', -1))
        self.dutyList = json.loads(arg.get('dutyList', "[]"))
        self.baseAbilityDic = json.loads(arg.get('baseAbilityDic', "{}"))
        self.potentialDic = json.loads(arg.get('potentialDic', "{}"))
        self.mgrSkill = int(arg.get('mgrSkill', -1))
        self.skills = json.loads(arg.get('skills', "[]"))
        self.cantSkills = json.loads(arg.get('cantSkills', "[]"))
        self.isNew = int(arg.get('isNew', 0))
        self.moodDA = arg.get('moodDA',
                              '{"moodFeedback":"0","salaryFeedback":"0","tiredFeedback":"0",''"latelyTiredLogs":"[]",'
                              '"otherMood":"{}"}')
        self.dataPrefs = arg.get('dataPrefs', "{}")
        self.dataPrefsList = arg.get('dataPrefsList', "{}")

    def __str__(self):
        return str(self.__dict__)

    def set_potential(self, ability_type, value):
        val = min(value, self.MaxPotential)
        self.potentialDic[ability_type] = val

    def set_base_ability(self, ability_type, value):
        self.baseAbilityDic[ability_type] = value

    def add_skill(self, skill):
        self.skills.append(skill)
        clerk_skills_vo = clerk_skills_dic[skill]
        if skill not in self.cantSkills:
            self.cantSkills.append(skill)
        self.cantSkills.extend([m for m in clerk_skills_vo.mutex if m not in self.cantSkills])

    def max_hp(self):
        base_ability = self.baseAbilityDic[ClerkAbilityType.carry.name]
        num = 100 + base_ability * 4
        if num > 1000:
            num = 1000
        return num

    def get_skill_prefer_count(self, value):
        num = 0
        for skill in self.skills:
            if clerk_skills_dic[skill].prefer == value:
                num += 1
        return num

    def get_default_salary(self):
        num = float(sum(v for k, v in self.baseAbilityDic.items() if k != ClerkAbilityType.luck.name) / 900 * 500)
        num2 = float((self.get_skill_prefer_count(1) + self.get_skill_prefer_count(-1) + -1) + 0.05)
        num3 = int(num * (1 + num2))
        if num3 < 10:
            num3 = 10
        return num3

    def add_all_duty(self):
        self.dutyList.clear()
        for duty in ClerkDutyType:
            self.dutyList.append(duty.value)


class GQXDJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (ClerkSPInfoVO, ClerkSkillsVO)):
            return obj.__dict__
        if isinstance(obj, ClerkData):
            clerk_data_dict = obj.__dict__
            for key in ['id', 'spID', 'entryDay', 'lv', 'baseLV', 'exp', 'eduType', 'majorType', 'defaultSalary',
                        'salary', 'hp', 'job', 'mgrSkill', 'isNew']:
                clerk_data_dict[key] = str(clerk_data_dict[key])
            for key in ['dutyList', 'baseAbilityDic', 'potentialDic', 'skills', 'cantSkills']:
                clerk_data_dict[key] = json.dumps(clerk_data_dict[key], separators=(',', ':'))
            return clerk_data_dict
        return super().default(obj)


def create_sp_clerk_data(sp_id):
    clerk_data = ClerkData()
    clerk_data.spID = sp_id
    sp_vo = clerk_sp_info_dic[sp_id]
    clerk_data.name = sp_vo.name
    clerk_data.headAssets = sp_vo.asset
    clerk_data.bodyAssets = sp_vo.asset
    clerk_data.lv = sp_vo.defaultLv
    clerk_data.baseLV = clerk_data.lv
    clerk_data.eduType = sp_vo.defaultEdu
    clerk_data.majorType = sp_vo.defaultMajor
    for clerk_ability_type in sp_vo.defaultPotential.keys():
        clerk_data.set_potential(clerk_ability_type, sp_vo.defaultPotential[clerk_ability_type])
        clerk_data.set_base_ability(clerk_ability_type, sp_vo.defaultAbility[clerk_ability_type])
    for skill in sp_vo.defaultSkills:
        if skill not in clerk_data.skills:
            clerk_data.add_skill(skill)
    if sp_vo.mgrSkill != -1:
        clerk_data.mgrSkill = sp_vo.mgrSkill
    clerk_data.hp = clerk_data.max_hp()
    clerk_data.isNew = 1
    clerk_data.defaultSalary = clerk_data.get_default_salary()
    clerk_data.salary = clerk_data.defaultSalary
    clerk_data.job = -1
    return clerk_data


def clerk_sp_info_init():
    with open(current_directory + '/clerkSPInfo.json', 'r', encoding='utf-8') as f:
        clerk_sp_info_json = json.load(f)
        for k, v in clerk_sp_info_json.items():
            clerk_sp_info_dic[int(str(k))] = ClerkSPInfoVO(v)


def clerk_skills_init():
    with open(current_directory + '/clerkSkills.json', 'r', encoding='utf-8') as f:
        clerk_skills_json = json.load(f)
        for k, v in clerk_skills_json.items():
            clerk_skills_dic[int(str(k))] = ClerkSkillsVO(v)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--file', nargs=1, required=True,
                        help='怪奇小店存档文件')
    parser.add_argument('-m', '--money', nargs='?', const='-', required=False,
                        help='修改金钱')
    parser.add_argument('-c', '--coin', nargs='?', const='-', required=False,
                        help='修改铜币')
    parser.add_argument('--addallsp', action='store_true', required=False,
                        help='添加所有特殊店员')
    parser.add_argument('--fullability', action='store_true', required=False,
                        help='修改所有店员满属性')
    parser.add_argument('--zerosalary', action='store_true', required=False,
                        help='修改所有员工薪水为零')
    parser.add_argument('--allskills', action='store_true', required=False,
                        help='添加所有正面技能')
    args = parser.parse_known_args()

    clerk_sp_info_init()
    clerk_skills_init()

    with open(args[0].file[0], 'r', encoding='utf-8') as f:
        game_save = json.load(f)

    game_currency = json.loads(game_save['gameCurrency'])
    clerk_list = []
    for clerk_str in json.loads(game_save['clerkList']):
        clerk_list.append(ClerkData(json.loads(clerk_str)))

    save_changed = False

    if args[0].money:
        print('money({})'.format(game_currency['1']))
        if args[0].money.isdigit():
            game_currency['1'] = int(args[0].money)
            print('money changed({})'.format(game_currency['1']))
            save_changed = True

    if args[0].coin:
        print('coin({})'.format(game_currency['2']))
        if args[0].coin.isdigit():
            game_currency['2'] = int(args[0].coin)
            print('coin changed({})'.format(game_currency['2']))
            save_changed = True

    if args[0].addallsp:
        clerk_id_max = max(clerk_data.id for clerk_data in clerk_list)
        clerk_sp_id_list = [clerk_data.spID for clerk_data in clerk_list]
        sp_vo_id_list = [clerk.id for clerk in clerk_sp_info_dic.values()]
        sp_add_list = [sp_id for sp_id in sp_vo_id_list if sp_id not in clerk_sp_id_list]
        if sp_add_list:
            for sp_id in sp_add_list:
                clerk_data = create_sp_clerk_data(sp_id)
                clerk_data.add_all_duty()
                clerk_data.job = 0
                clerk_data.id = clerk_id_max + 1
                clerk_list.append(clerk_data)
                clerk_id_max += 1
                print('add clerk: name({}), desc({})'.format(clerk_data.name, clerk_sp_info_dic[sp_id].desc))
            print('addallsp done')
            save_changed = True

    if args[0].fullability:
        for clerk_data in clerk_list:
            for k, v in clerk_data.potentialDic.items():
                if v > clerk_data.baseAbilityDic[k]:
                    clerk_data.baseAbilityDic[k] = v
            clerk_data.lv = 6
        print('fullability done')
        save_changed = True

    if args[0].zerosalary:
        for clerk_data in clerk_list:
            clerk_data.defaultSalary = 0
            clerk_data.salary = 0
        print('zerosalary done')
        save_changed = True

    if args[0].allskills:
        prefer_skills = [skill for skill in clerk_skills_dic.values() if skill.isRandom and skill.prefer > 0]
        for clerk_data in clerk_list:
            for skill in prefer_skills:
                if skill.id not in clerk_data.skills:
                    clerk_data.add_skill(skill.id)
        print('allskills done')
        save_changed = True

    if save_changed:
        clerk_json_list = [json.dumps(clerk_data, ensure_ascii=False, cls=GQXDJSONEncoder, separators=(',', ':'))
                           for clerk_data in clerk_list]

        game_save['gameCurrency'] = json.dumps(game_currency, ensure_ascii=False, separators=(',', ':'))
        game_save['clerkList'] = json.dumps(clerk_json_list, ensure_ascii=False, separators=(',', ':'))

        filename, ext = os.path.splitext(args[0].file[0])
        save_new_file = filename + '_new' + ext
        with open(save_new_file, 'w', encoding='utf-8') as f:
            json.dump(game_save, f, ensure_ascii=False, separators=(',', ':'))

        print('write {} done'.format(save_new_file))


if __name__ == '__main__':
    main()
